--[[
Name: unitDoodles.config
Author: Sonora (The Dragonflight, US Kirin Tor)
Website & SVN: http://code.google.com/p/browniehelper/source/browse/#svn/trunk/unitDoodles.config
License: GNU General Public License v3
]]

local defaultNewPosition = {'TOP','TOP',0,0}

--[[
handlerType signature:  f(name, desc) returns handler
handler signature:  f(doodle, property, updateConfig, reloadPanel) returns OptionsTable
--]]

local handlerTypes = {

    numeric = function(name, desc, order) 
        return function(doodle, property, updateConfig, reloadPanel)
            return  {
                type = 'input',
                name = name,
                desc = desc,
                width = 'half',
                pattern = '%d',
                get = function() return tostring(doodle[property]) end,
                set = function(info, value)
                        doodle[property] = tonumber(value)
                        updateConfig()
                end,
                order = order,
            } end
        end,
    
    boolean = function(name, desc, order) 
        return function(doodle, property, updateConfig, reloadPanel)
            return  {
                type = 'toggle',
                name = name,
                desc = desc,
                width = 'normal',
                get = function() return doodle[property] end,
                set = function(info, value)
                        doodle[property] = value
                        updateConfig()
                end,
                order = order,
            } end
        end,
    
    text = function(name, desc, order) 
        return function(doodle, property, updateConfig, reloadPanel)
            return  {
                type = 'input',
                name = name,
                desc = desc,
                width = 'normal',
                get = function() return doodle[property] end,
                set = function(info, value)
                        doodle[property] = value
                        updateConfig()
                end, 
                order = order,
            } end
        end,
    
    color = function(name, desc, order) 
        return function(doodle, property, updateConfig, reloadPanel)
            return  {
                type = 'color',
                name = name,
                desc = desc,
                hasAlpha = true,
                get = function() return unpack(doodle[property]) end,
                set = function(info, r, g, b, a)
                        doodle[property] = {r,g,b,a}
                        updateConfig()
                end,
                order = order,
            } end
        end,
    
    selection = function(name, desc, values, order)
        return function(doodle, property, updateConfig, reloadPanel)
            return  {
                type = 'select',
                name = name,
                desc = desc,
                values = values,
                get = function() return doodle[property] end,
                set = function(info, value)
                        doodle[property] = value
                        updateConfig()
                end,
                order = order,
            } end
        end,
    
    label = function(name, desc, order)
        return function(doodle, property, updateConfig, reloadPanel)
            return {
                type = 'description',
                name = name..": "..tostring(doodle[property]),
                order = order,
            }
            end
        end,
    
}

--Positions can be single entries or a set of constraints
local function constraintGroup(name, positionTable, updateConfig) 
    return  {
        type = 'group',
        name = name,
        guiInline = true,
        args = {
            pointOnParent = {
                type = 'select',
                name = 'Parent point',
                desc = 'The side/corner of the parent unit frame this doodle is anchored to',
                values = {TOP='Top side', RIGHT='Right side', BOTTOM='Bottom side', LEFT='Left side', TOPRIGHT='Top right corner', TOPLEFT='Top left corner', BOTTOMLEFT='Bottom left corner', BOTTOMRIGHT='Bottom right corner', CENTER='Center'},
                get = function() return positionTable.pointOnParent end,
                set = function(info, value) 
                    positionTable.pointOnParent = value
                    updateConfig()
                end,
                order = 1,
            },
            pointOnThis = {
                type = 'select',
                name = 'Doodle point',
                desc = 'The side/corner of the doodle that is anchored to the Parent point',
                values = {TOP='Top side', RIGHT='Right side', BOTTOM='Bottom side', LEFT='Left side', TOPRIGHT='Top right corner', TOPLEFT='Top left corner', BOTTOMLEFT='Bottom left corner', BOTTOMRIGHT='Bottom right corner', CENTER='Center'},
                get = function() return positionTable.pointOnThis end,
                set = function(info, value) 
                    positionTable.pointOnThis = value 
                    updateConfig()
                end,
                order = 2,
            },
            x = {
                type = 'input',
                name = 'X offset',
                desc = 'Horizontal offset.  A value of 0 centers the doodle on the anchor point, positive values move doodles to the right, negative values move doodles to the left.',
                width = 'half',
                pattern = '%d',
                get = function() return tostring(positionTable.x) end,
                set = function(info, value)
                        positionTable.x = tonumber(value)
                        updateConfig()
                end,
                order = 3,
            },
            y = {
                type = 'input',
                name = 'Y offset',
                desc = 'Vertical offset.  A value of 0 centers the doodle on the anchor point, positive values move doodles up, negative values move doodles down.',
                width = 'half',
                pattern = '%d',
                get = function() return tostring(positionTable.y) end,
                set = function(info, value)
                        positionTable.y = tonumber(value)
                        updateConfig()
                end,
                order = 4,
            },
        }
    }
end

handlerTypes.position = function(name, desc, order) 
    return function(doodle, property, updateConfig, reloadPanel)
    
        --Create a group to hold constraint groups
        positionContainer = {
            type = 'group',
            name = 'Position',
            desc = desc,
            guiInline = true,
            order = order,
            args = {
                positionType = {
                    type = 'select',
                    name = 'Method',
                    desc = 'Defines the positioning method.  "Fixed point" defines a static relationship between the doodle and the unit frame it is being drawn on.  "Advance"  positions the doodle relative to the preceeding doodle in the set.  "Stack"  positions the doodle relative to the closest VISIBLE doodle.',
                    values = {setPoint="Fixed point", advancePosition="Advance", stackPosition="Stack"},
                    get = function() 
                        return property
                    end,
                    set = function(info, value) 
                        local positionTable = doodle[property]
                        doodle[property] = nil
                        doodle[value] = positionTable
                        property = value --TODO:  will this work?  or do we have to reload the panel?
                        updateConfig()
                    end,
                    order = 1,
                },
        
                addContraint = {
                    type = 'execute',
                    name = 'Add anchor',
                    desc = 'Adds a new anchor point between the doodle and the parental unit frame.  Together anchor points and size suggestions determine the position and size of doodles.',
                    func = function()
                        table.insert(doodle[property], defaultNewPosition)
                        updateConfig()
                        reloadPanel()
                    end,
                    order = 2,
                },
            }
        }
    
        --Add an arg entry for each position contraint
        if type(doodle[property][1]) == 'table' then
            
            for i, positionHash in ipairs(doodle[property]) do
        
                local positionTable = {pointOnParent=positionHash[2], pointOnThis=positionHash[1], x=positionHash[3], y=positionHash[4]}
                local function positionUpdateConfig()
                    doodle[property][i] = {positionTable.pointOnParent, positionTable.pointOnThis, positionTable.x, positionTable.y}
                    updateConfig()
                end
        
                local newGroup = constraintGroup("Anchor "..tostring(i), positionTable, positionUpdateConfig)
                if i > 1 then
                    newGroup.args.remove = {
                        type = 'execute',
                        name = 'Remove anchor',
                        desc = 'Remove this anchor point.',
                        func = function()
                            table.remove(doodle[property], i)
                            updateConfig()
                            reloadPanel()
                        end,
                        order = 100,
                    }
                end
            
                newGroup.order = 10 + i
                positionContainer.args["Anchor "..tostring(i)] = newGroup
            end
        
        else
        
            local positionHash = doodle[property]
            local positionTable = {pointOnParent=positionHash[1], pointOnThis=positionHash[2], x=positionHash[3], y=positionHash[4]}
        
            local function positionUpdateConfig()
                doodle[property] = {positionTable.pointOnParent, positionTable.pointOnThis, positionTable.x, positionTable.y}
                updateConfig()
            end
        
            local newGroup = constraintGroup("Anchor Point", positionTable, positionUpdateConfig)
            newGroup.order = 10
            positionContainer.args["Anchor Point"] = newGroup
        
        end
    
        return positionContainer
    
    end
end

--Select texture handler based on whether or not SharedMedia are available
local function keyFromValue(t, value)
    for k,v in pairs(t) do
        if v == value then return k end
    end
end

local widgetsLoaded = IsAddOnLoaded('SharedMedia')
if widgetsLoaded then

    --Texture handler
    handlerTypes.texture = function(name, desc, order)
        return function(doodle, property, updateConfig, reloadPanel)
            return {
                type = 'select',
                name = name,
                desc = desc,
                dialogControl = 'LSM30_Statusbar',
                values = AceGUIWidgetLSMlists.statusbar,
                get = function() return keyFromValue(AceGUIWidgetLSMlists.statusbar, doodle[property]) end,
                set = function(info, key)
                    doodle[property] = AceGUIWidgetLSMlists.statusbar[key]
                    updateConfig()
                end,
                order = order,
            }
        end
    end
    
else
    --Text handler
    handlerTypes.texture = function(name, desc, order) 
        return function(doodle, property, updateConfig, reloadPanel)
            return  {
                type = 'input',
                name = name,
                desc = desc,
                width = 'normal',
                get = function() return doodle[property] end,
                set = function(info, value)
                        doodle[property] = value
                        updateConfig()
                end,
                order = order,
            } end
        end
        
end


--[[
Maps propertyName to a UI element generation call (handler)
]]--
local handlers = {

    --Numeric
    height = handlerTypes.numeric('Height','Sets the height of this doodle', 80),
    width = handlerTypes.numeric('Width', 'Sets the width of this doodle', 81),
    frameLevel = handlerTypes.numeric('Frame level', "Sets the doodle's frame level, which determines what it is drawn on top of.", 30),
    possibleStacks = handlerTypes.numeric('Possible stacks','The total number of stacks possible for this aura/buff/spell', 25),
    
    --Boolean
    onlyShowMine = handlerTypes.boolean('Only show mine','Only show auras cast by you, not other players.', 11),
    
    --Text
    aura = handlerTypes.text('Aura','The name of the aura/spell/buff which is being monitored by this doodle.', 10),
    
    --Color
    presentColor = handlerTypes.color('Present color', 'Color used when the doodle is being shown.', 20),
    missingColor = handlerTypes.color('Hidden color', 'Color used when the doodle is being "hidden".', 21),
    barColor = handlerTypes.color('Bar color', "Color for this doodle's bar texture.", 22),
    fullStackBarColor = handlerTypes.color('Full stack color', "Color used for this doodle's bar when the stacking buff/debuff is at a full stack.", 23),
    
    --Selection
    blendMode = handlerTypes.selection('Blend mode','Sets the method used to blend the doodle texture onto the unit frame.', {DISABLE='Disabled (opaque)',BLEND='Blend (recommended)',ALPHAKEY='One-bit alpha',ADD='Additive blend', MOD='Modulating blend'}, 31),
    frameStrata = handlerTypes.selection('Frame strata', 'Sets the layer on which the doodle is drawn.  Trying increasing the strata if your doodles are being hidden behind your unit frames.', {TOOLTIP='Tooltip', FULLSCREEN_DIALOG='Fullscreen dialog', FULLSCREEN='Fullscreen', DIALOG='Dialog', HIGH='High', MEDIUM='Medium', LOW='Low', BACKGROUND='Background'}, 32),
    direction = handlerTypes.selection('Orientation', 'Sets the orientation of the doodle to be vertical or horizontal.', {VERTICAL='Vertical', HORIZONTAL='Horizontal'}, 33),
    
    --Position
    setPoint = handlerTypes.position('Position','Sets anchor points between the doodle and parental unit frame.', 90),
    advancePosition = handlerTypes.position('Position','Sets anchor points between the doodle and parental unit frame.', 91),
    stackPosition = handlerTypes.position('Position','Sets anchor points between the doodle and parental unit frame.', 92),
    
    --Texture
    texture = handlerTypes.texture('Texture', 'Texture used to draw this doodle.', 15),
    
    --TODO
    --backdrop = ,
    
}


function unitDoodlesConfig:getPropertyHandler(doodle, propertyName, updateConfig, reloadPanel)

    --Attempt to retrieve a handler by propertyName
    local handler = handlers[propertyName]
    if handler == nil then
        handler = handlerTypes.label(propertyName,'This value cannot be set through unitDoodles.config.  Please edit config.lua in the unitDoodles directory to changes this property value.')
    end

    return handler(doodle, propertyName, updateConfig, reloadPanel)

end

function unitDoodlesConfig:hasHandler(propertyName)
    return handlers[propertyName] ~= nil
end

function unitDoodlesConfig:getHandlers()
    return handlers
end
